"""
Copyright 2008 Olivier Belanger

This file is part of Ounk.

Ounk is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Ounk is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Ounk.  If not, see <http://www.gnu.org/licenses/>.
"""
import wx

FONTSIZE = 8

class MyPrintout(wx.Printout):
    def __init__(self, text, title, margins):
        wx.Printout.__init__(self, title)
        self.lines = text
        self.margins = margins

    def HasPage(self, page):
        return page <= self.numPages

    def GetPageInfo(self):
        return (1, self.numPages, 1, self.numPages)

    def CalculateScale(self, dc):
        ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
        ppiScreenX, ppiScreenY = self.GetPPIScreen()
        logScale = float(ppiPrinterX) / float(ppiScreenX)
        
        pw, ph = self.GetPageSizePixels()
        dw, dh = dc.GetSize()
        scale = logScale * float(dw) / float(pw)
        dc.SetUserScale(scale, scale)
        self.logUnitsMM = float(ppiPrinterX) / (logScale * 25.4)
        
    def CalculateLayout(self, dc):
        topLeft, bottomRight = self.margins
        dw, dh = dc.GetSize()
        self.x1 = topLeft.x * self.logUnitsMM
        self.y1 = topLeft.y * self.logUnitsMM
        self.x2 = (dc.DeviceToLogicalXRel(dw) - bottomRight.x * self.logUnitsMM)
        self.y2 = (dc.DeviceToLogicalYRel(dh) - bottomRight.y * self.logUnitsMM)
        self.pageHeight = self.y2 - self.y1 - 2 * self.logUnitsMM
        font = wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
        dc.SetFont(font)
        self.lineHeight = dc.GetCharHeight()
        self.linesPerPage = int(self.pageHeight / self.lineHeight)
        
    def OnPreparePrinting(self):
        dc = self.GetDC()
        self.CalculateScale(dc)
        self.CalculateLayout(dc)
        self.numPages = len(self.lines) / self.linesPerPage
        if len(self.lines) % self.linesPerPage != 0:
            self.numPages += 1
        
    def OnPrintPage(self, page):
        dc = self.GetDC()
        self.CalculateScale(dc)
        self.CalculateLayout(dc)
        dc.SetPen(wx.Pen("gray", 0))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        r = wx.RectPP((self.x1, self.y1), (self.x2, self.y2))
        dc.DrawRectangleRect(r)
        dc.SetClippingRect(r)
        
        line = (page-1) * self.linesPerPage
        x = self.x1 + self.logUnitsMM
        y = self.y1 + self.logUnitsMM
        dc.SetPen(wx.Pen("black", 0))
        while line < (page * self.linesPerPage):
            dc.DrawText(self.lines[line], x, y)
            y += self.lineHeight
            line += 1
            if line >= len(self.lines):
                break

        return True
        
class Printer():
    def __init__(self, frame):
        self.pdata = wx.PrintData()
        self.pdata.SetPaperId(wx.PAPER_LETTER)
        self.pdata.SetOrientation(wx.PORTRAIT)
        self.margins = (wx.Point(15,15), wx.Point(15,15))
        self.frame = frame

    def OnPageSetup(self):
        data = wx.PageSetupDialogData()
        data.SetPrintData(self.pdata)
        data.SetDefaultMinMargins(True)
        data.SetMarginTopLeft(self.margins[0])
        data.SetMarginBottomRight(self.margins[1])
        dlg = wx.PageSetupDialog(self.frame, data)
        if dlg.ShowModal() == wx.ID_OK:
            data = dlg.GetPageSetupData()
            self.pdata = wx.PrintData(data.GetPrintData())
            self.pdata.SetPaperId(data.GetPaperId())
            self.margins = (data.GetMarginTopLeft(), data.GetMarginBottomRight())
        dlg.Destroy()  

    def OnPrintPreview(self, text, doc_name):
        data = wx.PrintDialogData(self.pdata)
        print1 = MyPrintout(text, doc_name, self.margins)
        print2 = MyPrintout(text, doc_name, self.margins)
        preview = wx.PrintPreview(print1, print2, data)
        if not preview.Ok():
            MessageBox("Unable to display preview of document.")
        else:
            preview_window = wx.PreviewFrame(preview, self.frame, "Print Preview - %s" % doc_name)
            preview_window.Initialize()
            preview_window.SetPosition(self.frame.GetPosition())
            preview_window.SetSize(self.frame.GetSize())
            preview_window.MakeModal(True)
            preview_window.Show(True)

    def OnPrint(self, text, doc_name):
        data = wx.PrintDialogData(self.pdata)
        printer = wx.Printer(data)
        printout = MyPrintout(text, doc_name, self.margins)
        printer.Print(self.frame, printout, True)
        self.pdata = wx.PrintData(printer.GetPrintDialogData().GetPrintData())
        printout.Destroy()  